package tcln.sors.model.order.dom;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Type;
import org.hibernate.validator.Length;
import org.hibernate.validator.Min;
import org.hibernate.validator.NotNull;

import tcln.sors.model.base.dom.AbstractSorsNamedEntity;
import tcln.sors.model.base.dom.DeliverableEntity;
import tcln.sors.model.product.dom.Product;

/**
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 * 
 */
@Entity
@Table(name = "TBL_ORDER_ITEM")
@AttributeOverrides({ @AttributeOverride(name = "id", column = @Column(name = "ORDER_ITEM_ID")) })
public class OrderItem extends AbstractSorsNamedEntity implements DeliverableEntity {
    private static final long serialVersionUID = 1L;

    private Order order;
    private Product product;
    private Integer quantity;
    private Date deliveryDate;
    private Date creationDate;
    private Date expiryDate;
    private Integer remindBefore;
    private boolean nailed;
    private boolean stuck;
    private boolean held;
    private String specialRequest;
    private List<OrderItemHist> histories = new ArrayList<OrderItemHist>();

    /**
     * Returns current value of {@link #order}.
     * 
     * @return the {@link #order}.
     */
    @ManyToOne
    @NotNull
    @JoinColumn(name = "ORDER_ID")
    public Order getOrder() {
        return order;
    }

    /**
     * Sets new value for {@link #order}.
     * 
     * @param order
     *            the new order to set
     */
    public void setOrder(Order order) {
        this.order = order;
    }

    /**
     * Returns current value of {@link #product}.
     * 
     * @return the {@link #product}.
     */
    @NotNull
    @ManyToOne
    @JoinColumn(name = "PRODUCT_ID")
    public Product getProduct() {
        return product;
    }

    /**
     * Sets new value for {@link #product}.
     * 
     * @param product
     *            the new product to set
     */
    public void setProduct(Product product) {
        this.product = product;
    }

    /**
     * Returns current value of {@link #quantity}.
     * 
     * @return the {@link #quantity}.
     */
    @NotNull
    @Min(1)
    @Column(name = "QUANTITY")
    public Integer getQuantity() {
        return quantity;
    }

    /**
     * Sets new value for {@link #quantity}.
     * 
     * @param quantity
     *            the new quantity to set
     */
    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    /**
     * {@inheritDoc}
     */
    @Temporal(TemporalType.DATE)
    @Column(name = "DELIVERY_DATE")
    public Date getDeliveryDate() {
        return deliveryDate;
    }

    /**
     * {@inheritDoc}
     */
    public void setDeliveryDate(Date deliveryDate) {
        this.deliveryDate = deliveryDate;
    }

    /**
     * {@inheritDoc}
     */
    @NotNull
    @Temporal(TemporalType.DATE)
    @Column(name = "CREATION_DATE")
    public Date getCreationDate() {
        return creationDate;
    }

    /**
     * {@inheritDoc}
     */
    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    /**
     * {@inheritDoc}
     */
    @NotNull
    @Temporal(TemporalType.DATE)
    @Column(name = "EXPIRY_DATE")
    public Date getExpiryDate() {
        return expiryDate;
    }

    /**
     * {@inheritDoc}
     */
    public void setExpiryDate(Date expiryDate) {
        this.expiryDate = expiryDate;
    }

    /**
     * {@inheritDoc}
     */
    @Min(1)
    @Column(name = "REMIND_BEFORE")
    public Integer getRemindBefore() {
        return remindBefore;
    }

    /**
     * {@inheritDoc}
     */
    public void setRemindBefore(Integer remindBefore) {
        this.remindBefore = remindBefore;
    }

    /**
     * Returns current value of {@link #nailed}.
     * 
     * @return the {@link #nailed}.
     */
    @Type(type = "true_false")
    @Column(name = "NAILED")
    public boolean isNailed() {
        return nailed;
    }

    /**
     * Sets new value for {@link #nailed}.
     * 
     * @param nailed
     *            the new nailed to set
     */
    public void setNailed(boolean nailed) {
        this.nailed = nailed;
    }

    /**
     * Returns current value of {@link #stuck}.
     * 
     * @return the {@link #stuck}.
     */
    @Type(type = "true_false")
    @Column(name = "STUCK")
    public boolean isStuck() {
        return stuck;
    }

    /**
     * Sets new value for {@link #stuck}.
     * 
     * @param stuck
     *            the new stuck to set
     */
    public void setStuck(boolean stuck) {
        this.stuck = stuck;
    }

    /**
     * Returns current value of {@link #held}.
     * 
     * @return the {@link #held}.
     */
    @Type(type = "true_false")
    @Column(name = "HELD")
    public boolean isHeld() {
        return held;
    }

    /**
     * Sets new value for {@link #held}.
     * 
     * @param held
     *            the new held to set
     */
    public void setHeld(boolean held) {
        this.held = held;
    }

    /**
     * Returns current value of {@link #specialRequest}.
     * 
     * @return the {@link #specialRequest}.
     */
    @Length(max = 100)
    @Column(name = "SPECIAL_REQUEST")
    public String getSpecialRequest() {
        return specialRequest;
    }

    /**
     * Sets new value for {@link #specialRequest}.
     * 
     * @param specialRequest
     *            the new specialRequest to set
     */
    public void setSpecialRequest(String specialRequest) {
        this.specialRequest = specialRequest;
    }

    /**
     * Returns current value of {@link #histories}.
     * 
     * @return the {@link #histories}.
     */
    @OneToMany(mappedBy = "orderItem", cascade = { CascadeType.ALL })
    public List<OrderItemHist> getHistories() {
        return histories;
    }

    /**
     * Sets new value for {@link #histories}.
     * 
     * @param histories
     *            the new histories to set
     */
    public void setHistories(List<OrderItemHist> histories) {
        this.histories = histories;
    }
}
